package com.shelpe.services.algorithm.autoDrive;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.shelpe.services.algorithm.client.LexiconClient;
import com.shelpe.services.algorithm.client.LexiconClient.RecommendWordDto;
import com.shelpe.services.algorithm.client.SinbadClient;
import com.shelpe.services.algorithm.configuration.MobileQscoreProperties;
import com.shelpe.services.algorithm.entity.jpa.Adgroup;
import com.shelpe.services.algorithm.entity.jpa.AutoProductQueue;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public abstract class MobileRecommendWordFilter implements RecommendWordFilter {
	
	public abstract List<SinbadClient.HandlingKeyword> filter(List<RecommendWordDto> recommends, AutoProductQueue queue, Adgroup adgroup);
	
	protected SortRes sort(List<RecommendWordDto> recommends) {
		AutoWordDto maxWord = new AutoWordDto();
		List<AutoWordDto> words = new ArrayList<AutoWordDto>();
		float totalCtr = 0;
		int countCtr = 0;
		for(LexiconClient.RecommendWordDto rw: recommends){
			AutoWordDto word = new AutoWordDto();
			word.recomend = rw;
			word.score = 0;
			words.add(word);
			maxWord.ctr = Math.max(maxWord.ctr, rw.getClickRatio());
			maxWord.pv = Math.max(maxWord.pv, rw.getImpression());
			maxWord.coverage = Math.max(maxWord.coverage, rw.getClickCoverage());
			if("combine".equals(rw.getOrigin())){
				rw.setPertinence(45);
			}else{
				rw.setPertinence(rw.getPertinence() * 10);
			}
			maxWord.pertinence = Math.max(maxWord.pertinence, rw.getPertinence());
			if(rw.getClickRatio() > 0){
				totalCtr = totalCtr + rw.getClickRatio();
				countCtr = countCtr + 1;
			}
		}
		if(countCtr > 0){
			maxWord.averageCtr = totalCtr / countCtr;
		}else{
			maxWord.averageCtr = totalCtr;
		}
		maxWord.pv = Math.max(maxWord.pv, 1);
		maxWord.ctr = Math.max(maxWord.ctr, 0.01f);
		maxWord.pertinence = Math.max(maxWord.pertinence, 10);
		maxWord.coverage = Math.max(maxWord.coverage, 0.01f);
		log.debug("max: {}", maxWord);
		for(AutoWordDto word: words){
			word.score = (int) this.calcScore(word, maxWord);
			log.debug("word {} score: ", word.getRecomend().getWord(), word.getScore());
		}
		
		Collections.sort(words, new Comparator<AutoWordDto>(){
			@Override
			public int compare(AutoWordDto o1, AutoWordDto o2) {
				return o2.getScore() - o1.getScore();
			}
		});
		
		SortRes res = new SortRes();
		res.words = words;
		res.max = maxWord;
		return res;
	}
	
	protected float calcScore(AutoWordDto word, AutoWordDto maxWord){
		float score = (((float) word.getRecomend().getClickRatio()) / maxWord.ctr) * 30;
		score = score + (((float) word.getRecomend().getImpression()) / maxWord.pv) * 30;
		score = score + (((float) word.getRecomend().getPertinence()) / maxWord.pertinence) * 40;
		return score;
	}
	
	protected SinbadClient.HandlingKeyword toKeyword(AutoWordDto word,int defaultPrice, int maxPrice){
		SinbadClient.HandlingKeyword keyword = new SinbadClient.HandlingKeyword();
		keyword.setWord(word.getRecomend().getWord());
		int price = (int) (word.getRecomend().getAveragePrice() * 100);
		if(price == 0){
			price = (int) (word.getRecomend().getRecommendPrice() * 100);
		}
		price = this.getMobileQscoreProperties().calcMobilePriceBaseOnAverage(price);
		if(price == 0){
			price = defaultPrice;
		}
		price = Math.min(price, maxPrice);
		keyword.setMaxPrice(this.getMobileQscoreProperties().calcPcPrice(price));
		keyword.setMaxPrice(Math.max(keyword.getMaxPrice(), 5));
		keyword.setMaxMobilePrice(price);
		keyword.setMatchScope(4);
		keyword.setIsDefaultPrice(0);
		return keyword;
	}
	
	protected abstract MobileQscoreProperties getMobileQscoreProperties();

	@Data
	public static class SortRes{
		private AutoWordDto max;
		private List<AutoWordDto> words;
	}
	
	@Data
	public static class AutoWordDto{
		private LexiconClient.RecommendWordDto recomend;
		private int pv;
		private int score;
		private float ctr;
		private float coverage;
		private int pertinence;
		
		private float averageCtr;
	}


	@Override
	public boolean support(Adgroup adgroup, AutoProductQueue queue) {
		boolean isMobile = false;
		if(adgroup != null){
			isMobile = adgroup.getDriveType() == 2;
		}else if(queue != null){
			isMobile = queue.getFlag() == 1;
		}
		return isMobile;
	}
}
